const dns = require("dns");
const http = require("http");

/**
 * @returns {Promise<{ok:Boolean,msg:String,ips:string[]}>}
 */
function dnsGetIps() {
  return new Promise(resolve => {
    dns.resolve4("upload.qiniup.com", (err, addresses) => {
      if (err) {
        return resolve({
          ok: false,
          msg: `${err.message}`
        })
      }
      resolve({
        ok: true,
        msg: "ok",
        ips: addresses
      })
    })
  })
}

/**
 * @returns {Promise<{ips:string[]}>}
 */
function safelyGetIps() {
  const predefined_ips = [
    '128.1.233.107',
    '23.248.173.9',
    '128.1.97.50',
    '192.254.94.44',
    '128.1.97.51',
    '23.236.102.14',
    '23.236.102.15',
    '23.236.102.19'
  ];
  return new Promise(async resolve => {
    let o_getDnsIps = await dnsGetIps();
    if (!o_getDnsIps.ok) {
      return resolve({
        ips: predefined_ips
      })
    }
    resolve({
      ips: o_getDnsIps.ips
    })
  })
}

let best_ip = "";


/**
 * @returns {Promise<{ok:Boolean,msg:String,bestip:String}>}
 * @param {Boolean} cache 
 */
function getBestIp(cache = true) {
  return new Promise(async resolve => {
    if (cache && best_ip) {
      return resolve({
        ok: true,
        msg: "cache ok",
        bestip: best_ip
      })
    }
    let o_ips = await safelyGetIps();
    let ips = o_ips.ips;
    let response_time = Infinity;
    let current_bestip = "";
    for (let _ip of ips) {
      let t = (await testResponseTime(_ip)).time;
      if (t < response_time) {
        response_time = t;
        current_bestip = _ip;
      }
    }
    if (!!current_bestip) {
      best_ip = current_bestip;
      return resolve({
        ok: true,
        msg: "ok",
        bestip: current_bestip
      })
    }
    resolve({
      ok: false,
      msg: `未选出bestip`,
      bestip: ""
    })


  })
}

/**
 * @returns {Promise<{time:Number}>}
 * @param {String} ip 
 */
function testResponseTime(ip) {
  return new Promise(resolve => {
    let start_time = Date.now();
    let req = http.request({
      host: ip,
      method: "get",
      path: "/",
      headers: {
        "host": "upload.qiniup.com"
      }
    }, (res) => {
      let end_time = Date.now();
      resolve({ time: end_time - start_time });
    });
    req.on("error", (err) => {
      resolve({ time: Infinity });
    })

    req.write("");
    req.end();
  })
}


module.exports = {
  safelyGetIps,
  dnsGetIps,
  getBestIp,
}